using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Reflection;

using GURUCORE.Framework.Core;
using GURUCORE.Framework.Core.Data;
using GURUCORE.Framework.DataAccess.Provider;
using GURUCORE.Framework.DataAccess.ORMapping.CriteriaMapping;
//using GURUCORE.Framework.Core.Indexing;
//using GURUCORE.Framework.DataAccess.Indexing;

namespace GURUCORE.Framework.DataAccess.ORMapping
{
    public class TableMapper<T> : TableMapperNonGeneric where T : DTOBase 
	{		
		public TableMapper(): base()
		{
		}

		public TableMapper(string p_sGMetaTable) : base(p_sGMetaTable)
		{			
		}

		public TableMapper(string p_sGMetaTable, string p_sKeyField) : base(p_sGMetaTable, p_sKeyField)
		{			
		}       



      
        /// <summary>
        /// this is a wrapper for Generic TableMapper only, almost no business or processing different with TableMapperNonGeneric
        /// </summary>
        /// <param name="p_oCriteria"></param>
        /// <param name="p_arrColumn"></param>
        /// <returns></returns>
        public DTOCollection<T> GetObjects(Criteria p_oCriteria, params string[] p_arrColumn)
        {
            DataAccessContext oDACtx = DataAccessContext.GetDataAccessContext();
            
            string sSql = base._BuildGetObjectSqlQuery(oDACtx, typeof(T), p_oCriteria, p_arrColumn);

            //obtain connection
            IDbConnection oDbConn = oDACtx.GetConnection();
            //do query
            IDbCommand oDbCmd = oDACtx.GetDbCommand(oDbConn);
            oDbCmd.CommandText = sSql;
            oDbCmd.CommandType = CommandType.Text;

            IDataReader oDataReader;
            DTOCollection<T> arrDTOs = new DTOCollection<T>();

            try
            {
                oDataReader = oDbCmd.ExecuteReader();

                //if is concrete DTO, convert IDbDataReader into DTO
                if (m_sGMetaTable == null)
                {
                    arrDTOs = DataTransferObjectMaker.MakeDTO<T>(oDataReader);
                }
                //else, convert to GMetaDTO
                else
                {                    
                    arrDTOs.FromArray(
                            DataTransferObjectMaker.MakeGMetaDTO<T>(m_sGMetaTable, oDataReader, p_arrColumn)
                        );
                }
                oDataReader.Close();
            }
            catch (DbException ex)
            {
                GException.ProcessException(ex); // throw ex;
            }
            finally
            {
                oDACtx.ReturnConnection(oDbConn);
            }

            //return
            return arrDTOs;
        }


    }
}
